﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Resource;
using System.Collections.ObjectModel;
using Quartz;
using System.IO;
using Quartz.Impl;
using WPFSYN.Model;
using Newtonsoft.Json.Linq;
using WPFSYN.Quartz;

namespace WPFSYN
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public delegate void Write(string title, string SynMsg);
    public partial class MainWindow : Window
    {
        public static Write MyWrite;
        public static string rootPath = Directory.GetCurrentDirectory() + "\\Json\\";
        public static List<JsonData> list = new List<JsonData>();
        private static object begeditvalue;

        public MainWindow()
        {
            try
            {
                InitializeComponent();
                BindTreeView();
                CkImg.Source = new BitmapImage(new Uri(SynMsg.OffCheck, UriKind.Relative));
                CkTx.Text = SynMsg.CheckAll;
                BSynImg.Source = new BitmapImage(new Uri(SynMsg.OffSyn, UriKind.Relative));
                BSynTx.Text = SynMsg.BegSyn;
                ESynImg.Source = new BitmapImage(new Uri(SynMsg.OffStart, UriKind.Relative));
                ESynTx.Text = SynMsg.EndSyn;
                MfyImg.Source = new BitmapImage(new Uri(SynMsg.OffModify, UriKind.Relative));
                MfyTx.Text = SynMsg.Interval;
                Synlist.Header = SynMsg.SynList;
                SynMsgList.Header = SynMsg.MsgList;
                MfyBox.Header = SynMsg.Interval;
                NodeName.Header = SynMsg.NodeName;
                TimeType.Header = SynMsg.TimeType;
                SynTime.Header = SynMsg.SynTime;
                MyWrite = Write;
                SynchronizeJob.MyWrite = Write;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message,SynMsg.Caption);
            }
        }

        public class TreeNode
        {
            public string Name { get; set; }
            public IList<TreeNode> Children { get; set; }
            public bool IsChecked { get; set; }
            public bool Start { get; set; }
            public string Image { get; set; }
        }

        void Write(object title, object SynMsg)
        {
            try
            {
                listBox.Dispatcher.BeginInvoke(new Action(() =>
                {
                    if (listBox.Items.Count >= 500)
                        listBox.Items.Clear();
                    listBox.Items.Insert(0, $"{title}:{SynMsg.ToString()}");
                    listBox.Items.Refresh();
                }));
            }
            catch (Exception ex)
            {
                listBox.Items.Insert(0, $"{title}:委托方法Write{ex.Message}");
                listBox.Items.Refresh();
            }
        }

        public void BindTreeView()
        {
            treeView.Items.Clear();
            DirectoryInfo root = new DirectoryInfo(rootPath);
            FileInfo[] files = root.GetFiles();
            var treelist = new List<TreeNode>();
            if (files != null && files.Length > 0)
            {
                foreach (var item in files)
                {
                    if (item.Name.ToUpper().IndexOf(".JSON") > -1)
                    {
                        using (StreamReader file = File.OpenText(item.FullName))
                        {
                            using (JsonTextReader reader = new JsonTextReader(file))
                            {
                                JObject cfg = (JObject)JToken.ReadFrom(reader);
                                TreeNode tree = new TreeNode() {
                                    Name = $"{cfg["NodeName"].ToString()}({cfg["NodeDesc"].ToString()})",
                                    Image = SynMsg.RbtnOff,
                                    IsChecked = false
                                };
                                treelist.Add(tree);
                                JsonData model = JsonConvert.DeserializeObject<JsonData>(cfg.ToString());
                                model.FullName = item.FullName.ToString();
                                model.WebApi.Parameter = JsonConvert.DeserializeObject<List<WebApi.Parameters>>(cfg["WebApi"]["Parameter"].ToString());
                                list.Add(model);
                            }
                        }
                    }
                }
                treeView.ItemsSource = treelist;
            }
        }

        private static async Task StartShowTime(List<TreeNode> selectedNodes)
        {
            string node = string.Empty;
            // Grab the Scheduler instance from the Factory
            StdSchedulerFactory factory = new StdSchedulerFactory();
            IScheduler sched = await factory.GetScheduler();

            foreach (var item in selectedNodes)
            {
                node = item.Name.Substring(0, item.Name.IndexOf('('));
                JsonData model = list.Where(i => i.NodeName.Equals(node)).FirstOrDefault();
                ScheduleJob(model, sched);
                UpdateJsonStatus(model, "AreSynchronized");
            }
            sched.Start();
            list = GetJsonDataList();
        }

        private void RefreshTreeView(List<TreeNode> selectedNodes)
        {
            foreach (TreeNode item in treeView.Items)
            {
                var model = selectedNodes.Where(i => i.Name.Equals(item.Name)).FirstOrDefault();
                if (model != null)
                {
                    item.Start = model.Start;
                    item.Image = model.Image;
                    item.IsChecked = false;
                }
            }
            treeView.Items.Refresh();
        }

        public static List<JsonData> GetJsonDataList()
        {
            List<JsonData> list = new List<JsonData>();

            DirectoryInfo root = new DirectoryInfo(rootPath);
            FileInfo[] files = root.GetFiles();

            if (files != null && files.Length > 0)
            {
                foreach (var item in files)
                {
                    if (item.Name.ToUpper().IndexOf(".JSON") > -1)
                    {
                        using (System.IO.StreamReader file = System.IO.File.OpenText(item.FullName))
                        {
                            using (JsonTextReader reader = new JsonTextReader(file))
                            {
                                JObject cfg = (JObject)JToken.ReadFrom(reader);
                                JsonData model = JsonConvert.DeserializeObject<JsonData>(cfg.ToString());
                                model.FullName = item.FullName.ToString();
                                model.WebApi.Parameter = JsonConvert.DeserializeObject<List<WebApi.Parameters>>(cfg["WebApi"]["Parameter"].ToString());
                                list.Add(model);
                            }
                        }
                    }
                }
            }
            return list;
        }

        private static void UpdateJsonStatus(JsonData model, string status)
        {
            string jsonString = File.ReadAllText(model.FullName, Encoding.UTF8);//读取文件
            JObject jo = JObject.Parse(jsonString);//解析成json
            jo["Status"] = status;
            string convertString = Convert.ToString(jo);//将json装换为string
            File.WriteAllText(model.FullName, convertString);//将内容写进jon文件中
        }

        public static void ScheduleJob(JsonData model, IScheduler sched)
        {
            IJobDetail job = null;
            job = JobBuilder.Create<MyJob>()
                                   .WithIdentity(model.NodeName, $"{model.NodeName}_JobGroup")
                                   .UsingJobData("processName", model.NodeName.ToString())
                                   .Build();

            ITrigger trigger = null;
            if (model.NodeName.ToString().Equals("MATERIAL_ALARM") || model.NodeName.ToString().Equals("CARTON_EXPIRATION_ALARM"))
            {
                trigger = TriggerBuilder.Create()
                        .WithIdentity($"{model.NodeName}_Trigger", $"{model.NodeName}_TriggerGroup")
                        .WithDailyTimeIntervalSchedule(x => x.OnEveryDay().StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(08, 00)).EndingDailyAt(TimeOfDay.HourAndMinuteOfDay(08, 30)).WithIntervalInHours(1))
                        .Build();
            }
            else
            {
                switch (model.TimeType)
                {
                    case "小时":
                    default:
                        trigger = TriggerBuilder.Create()
                                 .WithIdentity($"{model.NodeName}_Trigger", $"{model.NodeName}_TriggerGroup")
                                 .StartAt(DateTime.Now)
                                 .WithSimpleSchedule(x => x.WithIntervalInMinutes(model.TimeIntervalBetween * 60)
                                 .RepeatForever())
                                 .Build();
                        break;
                    case "分钟":
                        trigger = TriggerBuilder.Create()
                                 .WithIdentity($"{model.NodeName}_Trigger", $"{model.NodeName}_TriggerGroup")
                                 .StartAt(DateTime.Now)
                                 .WithSimpleSchedule(x => x.WithIntervalInMinutes(model.TimeIntervalBetween)
                                 .RepeatForever())
                                 .Build();
                        break;
                }
            }
            sched.ScheduleJob(job, trigger);
        }

        private async Task UnScheduleJob(List<TreeNode> selectedNodes)
        {
            string node = string.Empty;
            foreach (TreeNode item in selectedNodes)
            {
                node = item.Name.Substring(0, item.Name.IndexOf('('));
                JsonData model = list.Where(i => i.NodeName.Equals(node)).FirstOrDefault();
                JobKey existKey = JobKey.Create(model.NodeName, $"{model.NodeName}_JobGroup");
                StdSchedulerFactory factory = new StdSchedulerFactory();
                IScheduler scheduler = await factory.GetScheduler();
                scheduler.PauseJob(existKey);
                TriggerKey exisTriggerKey = new TriggerKey($"{model.NodeName}_Trigger", $"{model.NodeName}_TriggerGroup");
                bool result = await scheduler.UnscheduleJob(exisTriggerKey);
                if (result)
                {
                    Write(model.NodeName, string.Format(SynMsg.SynStop, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), model.NodeName));
                    UpdateJsonStatus(model, "EndSynchronous");
                }
                else
                {
                    Write(model.NodeName, string.Format(SynMsg.SynStopFai, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), model.NodeName));
                }
            }
            list = GetJsonDataList();
        }

        private void Check_Click(object sender, RoutedEventArgs e)
        {
            TreeCheck(false);
            bool all = true;
            var list = new List<TreeNode>();
            foreach (TreeNode item in treeView.Items)
            {
                if (!item.IsChecked)
                {
                    item.IsChecked = true;
                    all = false;
                }
                else
                {
                    item.IsChecked = false;
                    all = true;
                }
                list.Add(item);
            }
            treeView.ItemsSource = list;
            string imageurl = all ? SynMsg.OffCheck : SynMsg.OnCheck;
            CkImg.Source = new BitmapImage(new Uri(imageurl, UriKind.Relative));
        }

        private void BegSyn_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                TreeCheck(false);
                var selectedNodes = new List<TreeNode>();
                foreach (TreeNode node in treeView.Items)
                {
                    if (node.IsChecked && !node.Start)
                    {
                        node.Start = true;
                        node.Image = SynMsg.RbtnOn;
                        selectedNodes.Add(node);
                    }
                }
                if (selectedNodes.Count <= 0)
                {
                    MessageBox.Show(SynMsg.CkOutSynNd, SynMsg.Caption);
                    return;
                }
                Write($"{ DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}", SynMsg.StartSyn);
                CkImg.Source = new BitmapImage(new Uri(SynMsg.OffCheck, UriKind.Relative));
                BSynImg.Source = new BitmapImage(new Uri(SynMsg.OnSyn, UriKind.Relative));
                ESynImg.Source = new BitmapImage(new Uri(SynMsg.OffStart, UriKind.Relative));
                StartShowTime(selectedNodes);
                RefreshTreeView(selectedNodes);
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format(SynMsg.SynBegErr, ex.Message), SynMsg.Caption);
            }
        }

        private void EndSyn_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                TreeCheck(false);
                List<TreeNode> selectedNodes = new List<TreeNode>();
                foreach (TreeNode node in treeView.Items)
                {
                    if (node.IsChecked && node.Start)
                    {
                        node.Start = false;
                        node.Image = SynMsg.RbtnOff;
                        selectedNodes.Add(node);
                    }
                }
                if (selectedNodes.Count <= 0)
                {
                    MessageBox.Show(SynMsg.CkStartSynNd, SynMsg.Caption);
                    return;
                }
                ESynImg.Source = new BitmapImage(new Uri(SynMsg.OnStart, UriKind.Relative));
                BSynImg.Source = new BitmapImage(new Uri(SynMsg.OffSyn, UriKind.Relative));
                CkImg.Source = new BitmapImage(new Uri(SynMsg.OffCheck, UriKind.Relative));
                UnScheduleJob(selectedNodes);
                RefreshTreeView(selectedNodes);
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format(SynMsg.SynEndErr, ex.Message), SynMsg.Caption);
            }
        }

        private void SynDte_Click(object sender, RoutedEventArgs e)
        {
            TreeCheck(true);
            TimeType.ItemsSource = new List<string>() { SynMsg.Hour, SynMsg.Minutes };
            MfyData.ItemsSource = list.Where(i => !i.Status.Equals("AreSynchronized")).ToList();
            MfyData.AutoGenerateColumns = false;
            if (MfyData.Columns.Count > 3)
            {
                for (int i = 3; i < MfyData.Columns.Count; i++)
                {
                    MfyData.Columns[i].Visibility = Visibility.Collapsed;
                }
            }
        }

        private void MfyData_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
        {
            try
            {
                var editvaule = e.EditingElement;
                var celleditvaule = string.Empty;
                if (e.Column.GetType().Name.Equals("DataGridComboBoxColumn"))
                    celleditvaule = (editvaule as ComboBox).Text;
                else
                    celleditvaule = (editvaule as TextBox).Text;
                if (object.Equals(begeditvalue, celleditvaule))
                    return;
                JsonData jsonData = e.Row.Item as JsonData;
                var model = list.Where(i => i.NodeName.Equals(jsonData.NodeName)).FirstOrDefault();
                string josnString = "";
                //c#文件流读文件 
                using (FileStream fsRead = new FileStream(model.FullName, FileMode.Open))
                {
                    int fsLen = (int)fsRead.Length;
                    byte[] heByte = new byte[fsLen];
                    int r = fsRead.Read(heByte, 0, heByte.Length);
                    josnString = Encoding.UTF8.GetString(heByte);
                }
                JObject jo = JObject.Parse(josnString);
                if (e.Column.SortMemberPath.Equals("TimeIntervalBetween"))
                    jo["TimeIntervalBetween"] = celleditvaule;
                else
                    jo["TimeType"] = celleditvaule;
                string convertString = Convert.ToString(jo);//将json装换为string
                byte[] myByte = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(jo));
                using (FileStream fsWrite = new FileStream(model.FullName, FileMode.Truncate))
                {
                    fsWrite.Write(myByte, 0, myByte.Length);
                };
                return;
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format(SynMsg.UpTime,ex.Message), SynMsg.Caption);
            }
        }

        private void MfyData_BeginningEdit(object sender, DataGridBeginningEditEventArgs e)
        {
            //ComboBox：DataGridComboBoxColumn   Text：DataGridTextColumn
            if (e.Column.GetType().Name.Equals("DataGridComboBoxColumn"))
                begeditvalue = (e.Column.GetCellContent(e.Row) as ComboBox).Text;
            else
                begeditvalue = (e.Column.GetCellContent(e.Row) as TextBlock).Text;
        }

        private void TreeCheck(bool synlistandmfybox)
        {
            SynMsgList.Visibility = synlistandmfybox ? Visibility.Hidden : Visibility.Visible;
            MfyBox.Visibility = synlistandmfybox ? Visibility.Visible : Visibility.Hidden;
            MfyImg.Source = new BitmapImage(new Uri(synlistandmfybox ? SynMsg.OnModify : SynMsg.OffModify, UriKind.Relative));
            if (treeView.Items == null || treeView.Items.Count <= 0)
            {
                MessageBox.Show(SynMsg.NoNd, SynMsg.Caption);
                return;
            }
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            foreach (var item in list)
            {
                item.Status = "EndSynchronous";
                var config = JsonConvert.SerializeObject(item);
                File.WriteAllText(item.FullName, config);
            }
        }
    }
}
